

from rest_framework import serializers
from goods.models import SKU,SKUSpecification,SPU
from goods.models import GoodsCategory,SPUSpecification,SpecificationOption


# 定义序列化器序列化选项表
class SpecOptModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = SpecificationOption
        fields = [
            'id',
            'value'
        ]


# 定义序列化器序列化规格表
class SPUSpecModerSerializer(serializers.ModelSerializer):
    spu = serializers.StringRelatedField()
    spu_id = serializers.IntegerField()

    # 代表的是，选项表的多条数据SpecificationOption
    options = SpecOptModelSerializer(many=True)

    class Meta:
        model = SPUSpecification
        fields = [
            'id',
            'name',
            'spu',
            'spu_id',
            'options'
        ]


# 定义一个序列化器来序列化SPU模型类
class SPUSimpleModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = SPU
        fields = [
            'id',
            'name'
        ]


# 定义一个分类表的序列化器
class GoodsCategoryModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = [
            'id',
            'name'
        ]


# 定义一个sku规格选项中间表的序列化器
class SKUSpecOptModelSerializer(serializers.ModelSerializer):
    # 类似于spec_id和option_id的这种外键关联的隐藏字段
    # 1、在序列化的时候可以不用指明
    # 2、但是，在反序列化校验的时候，必须手动指定
    spec_id = serializers.IntegerField()
    option_id = serializers.IntegerField()

    class Meta:
        model = SKUSpecification
        fields = [
            'spec_id',
            'option_id'
        ]


# 定义序列化器完成序列化操作SKU模型类
class SKUModelSerializer(serializers.ModelSerializer):
    spu = serializers.StringRelatedField() # 序列化成主表对象__str__返回的结果
    spu_id = serializers.IntegerField() # spu对象的主键隐藏字段
    category = serializers.StringRelatedField() # 序列化成分类名
    category_id = serializers.IntegerField() # 序列化成分类的id

    # 1、specs代表的是什么模型类数据
    # 答：代表的是SKUSpecification中间表的多条数据！！
    # 2、一个还是多个
    # 答：多个(查询集)
    # read_only设置为True，含义是：在反序列化的时候忽略中间表数据
    # 为什么要这么做？答：模型类给我们构建的create方法，无法帮我我们创建中间表数据的！！
    # specs = SKUSpecOptModelSerializer(many=True, read_only=True)
    specs = SKUSpecOptModelSerializer(many=True)

    class Meta:
        model = SKU
        fields = "__all__"


    def update(self, instance, validated_data):
        # 模型类序列化器无法帮助我们修改中间表信息
        specs = validated_data.pop('specs')

        # 1、更新sku主表数据
        SKU.objects.filter(pk=instance.id).update(**validated_data)
        # 2、更新中间数据(更新规格和选项)
        # 2.1 删除原有的中间表信息
        SKUSpecification.objects.filter(sku_id=instance.id).delete()
        # 2.2 从新构建中间表信息
        for spec in specs:
            # spec: 代表是单一的规格及其选项：{spec_id: "6", option_id: 13}
            spec['sku_id'] = instance.id
            # 构建一个中间表数据，保存新建sku的规格和选项信息
            SKUSpecification.objects.create(**spec)

        return instance



    def create(self, validated_data):
        # 在该方法里面，需要补充逻辑：根据前端传来的specs字段中指明的规格和选项信息，来构建中间表数据
        # 剔除新建sku对象时候，多余的specs字段
        specs = validated_data.pop('specs')

        # 1、创建主表对象sku
        # 由于目前有效数据中任然存在specs字段，而该字段代表的是中间表数据，无法用于主表对象sku的新建
        sku = SKU.objects.create(**validated_data)
        # 2、新建中间表数据
        # specs: [{spec_id: "6", option_id: 13}, {spec_id: "7", option_id: 20}]
        for spec in specs:
            # spec: 代表是单一的规格及其选项：{spec_id: "6", option_id: 13}
            spec['sku_id'] = sku.id
            # 构建一个中间表数据，保存新建sku的规格和选项信息
            SKUSpecification.objects.create(**spec)


        return sku





